home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / tex / diff.zip / DIFF.C < prev    next >
Text File  |  1986-03-11  |  12KB  |  408 lines

  1. /*  DIFF - File Comparator  */
  2.  
  3. /*
  4. Copyright (c) 1983 by Kevin B. Kenny
  5.  
  6.      This medium and the information contained herein are confidential to
  7. and the property of Kevin B. Kenny (the author) and are not to be disclosed
  8. to any third party without the written permission of the author or his
  9. designate.  The author also claims copyright to the material as an
  10. "unregistered unpublished work" under USC 13, Section 105 of the United
  11. States Copyright Act of 1976.
  12.  
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <ctype.h>
  17. #include <dos.h>
  18. #include "cmdutil.h"
  19.  
  20. /*  Command line options    */
  21.  
  22. int dispmode;               /* Display mode */
  23. #define DM_NORM 0           /* Normal display */
  24. #define DM_ALTER 1          /* Display alterations only */
  25. #define DM_MATCH 2          /* Display matching lines */
  26. #define MAXLINE 135
  27.  
  28. int resync;             /* Resynchronization count */
  29. char *header;           /* Header for display */
  30. int blanksf;            /* Flag = 1 if blanks s/b compressed */
  31. int single;             /* Flag = 1 to ignore case differences */
  32. char * file1;           /* Name of first file */
  33. char * file2;           /* Name of second file */
  34.  
  35. /*  Input file status   */
  36.  
  37. FILE * file [2];            /* IObuf's of input files */
  38.  
  39. struct file_line {
  40.     struct file_line *next, *prev;     /* Chain linkage */
  41.     int line_no;                       /* Line number in file */
  42.     char * line_text;                  /* Text of the line */
  43.     };
  44.  
  45. struct file_line * first_line [2];  /* First line from file in memory */
  46. struct file_line * last_line [2];   /* Last line from file in memory */
  47. struct file_line * cur_line [2];    /* Current line in memory */
  48. int linenumb [2];                   /* Last line read from each file */
  49. int eofhit [2];                     /* EOF read in from file */
  50.  
  51. /*  Status of resynchronizer    */
  52.  
  53. int equal;              /* Flag to indicate equality */
  54. int match;              /* Flag to indicate match reached */
  55. int left;               /* File being read backwards */
  56. int right;              /* FIle being read forwards */
  57. int loffset;            /* Number of mismatches in "left" */
  58. int roffset;            /* Number of mismatches in "right" */
  59. int difflen [2];        /* Number of mismatches by file */
  60. int hold;               /* Working word for pointer switches */
  61.  
  62. /*  Procedures to be defined below */
  63.  
  64. extern char *curline ();
  65.  
  66. main (argc, argv)
  67.   int argc;
  68.   char ** argv;
  69.   {
  70.  
  71.     fprintf(stderr, "K**2 DIFF MS-DOS version 85-05-09\n");
  72.     fprintf (stderr, "copyright (c) 1983, 1984, 1985 by Kevin Kenny.\n");
  73.     getopts(argc, argv);
  74.     setup();
  75.     rundiff();
  76.     }
  77.  
  78. /*  Read an process the options from the command line   */
  79.  
  80. static struct option optable [8] = {    /* Option descriptions for procarg */
  81. #define FILE_OPT -1
  82.         "Alterations", NAKED_KWD,
  83. #define ALTER_OPT 0         /* Flag to show just changed text */
  84.         "Matching", NAKED_KWD,
  85. #define MATCH_OPT 1         /* Flag to show just matching text */
  86.         "Resynchronize", NVAL_KWD,
  87. #define RESYN_OPT 2         /* Line count for resynchronization */
  88.         "Header", SVAL_KWD,
  89. #define HEAD_OPT 3          /* Header for output lines */
  90.         "Blanks", NAKED_KWD,
  91. #define BLANK_OPT 4         /* Ignore multiple blanks */
  92.         "Singlecase", NAKED_KWD,
  93. #define SINGLE_OPT 5
  94.         EOF};
  95.  
  96. getopts (argc, argv)
  97.   int argc;
  98.   char ** argv;
  99.   {
  100.  
  101.     int info;       /* Information item returned from procarg */
  102.     int error;      /* Error flag */
  103.  
  104.     dispmode = DM_NORM;     /* Set default options */
  105.     resync = 3;
  106.     header = "-------------------------------------------------- ";
  107.     blanksf = FALSE;
  108.     single = FALSE;
  109.     file1 = NULL;
  110.     file2 = NULL;
  111.  
  112.     ++argv; --argc;     /* Discard command name from argv */
  113.  
  114.     error = FALSE;      /* No error has occurred yet */
  115.  
  116.     while (argc) {      /* Process one command option */
  117.         switch(procarg (&argc, &argv, optable, &info)) {
  118.             case ALTER_OPT:
  119.                 dispmode = DM_ALTER; break;
  120.             case MATCH_OPT:
  121.                 dispmode = DM_MATCH; break;
  122.             case RESYN_OPT:
  123.                 resync = info; break;
  124.             case HEAD_OPT:
  125.                 header = info; break;
  126.             case BLANK_OPT:
  127.                 blanksf = TRUE; break;
  128.             case SINGLE_OPT:
  129.                 single = TRUE; break;
  130.             case FILE_OPT:
  131.                 if (file1 == NULL) file1 = info;
  132.                 else if (file2 == NULL) file2 = info;
  133.                 else error = TRUE;
  134.                 break;
  135.             default:
  136.                 error = TRUE;
  137.             }
  138.         }
  139.  
  140.     if (file2 == NULL || error) {
  141.         showsyntax("diff <file1> <file2>", optable);
  142.         exit();
  143.         }
  144.     }
  145.  
  146. /*  Set up the DIFF process     */
  147.  
  148. setup () {
  149.  
  150.     if ((file [0] = fopen(file1, "r")) == NULL) {
  151.         fprintf (stderr, "%s: can't open file.\n", file1);
  152.         exit();
  153.         }
  154.     if ((file [1] = fopen(file2, "r")) == NULL) {
  155.         fprintf(stderr, "%s: can't open file.\n", file2);
  156.         exit();
  157.         }
  158.     first_line[0] = first_line[1] =
  159.     last_line[0] = last_line[1] =
  160.     cur_line[0] = cur_line[1] =       NULL;
  161.     linenumb[0] = linenumb[1] = 0;
  162.     eofhit[0] = eofhit[1] = FALSE;
  163.     equal = TRUE;                   /* Initially, files are assumed equal */
  164.     fflush(stderr);
  165.     }
  166.  
  167. /*  Do the DIFF process     */
  168.  
  169. rundiff () {
  170.     while (!ateof(0) || !ateof(1)) {  /* Run until end of files */
  171.         domatch();         /* Handle matching lines */
  172.         if (ateof(0) && ateof(1)) break;
  173.         equal = FALSE;      /* We've found a difference */
  174.         synch();           /* Get us back in sync */
  175.         dodiff();          /* Handle changed lines */
  176.         }
  177.     if (equal) fprintf(stderr,"\nThe files are equal\n");
  178.     }
  179.  
  180. /*  Do matching lines       */
  181.  
  182. domatch () {
  183.     if (!atmatch()) return;        /* Handle non-match at start */
  184.     
  185.     if (dispmode == DM_MATCH)       /* Displaying matches? */
  186.         printf("%s%d, %d\n", header, lineno (0), lineno (1));
  187.  
  188.     while (atmatch() && !ateof(0)) {
  189.         if (dispmode == DM_MATCH)   /* Display matching lines */
  190.             printf("%s", curline (0));
  191.         advance(0); advance(1);   /* Bump past matching lines */
  192.         discard(0); discard(1);   /* Throw away matched lines */
  193.         }
  194.     }
  195.  
  196. /*  Resynchronize comparison when mismatched lines found    */
  197.  
  198. synch () {
  199.     left = 0;                   /* Move pointer leftward from
  200.                                    current position in first file */
  201.     right = 1;                  /* Move pointer rightward in second
  202.                                    file. */
  203.     loffset = roffset = 0;      /* Both pointers at current line */
  204.  
  205.     do {
  206.         ++roffset; advance(right);              /* Move pointer rightward */
  207.         if (--loffset >= 0) backup (left);      /* Back leftward pointer up */
  208.         else {                           /* Pointer reached divergence point */
  209.             chkabrt();
  210.             hold = right; right = left; left = hold;     /* Swap input files */
  211.             loffset = roffset; roffset = 0;              /* Switch pointers */
  212.             }
  213.  
  214.         match = TRUE;                      /* Innocent until proven guilty */
  215.         for (hold = 0; hold < resync; ++hold) {
  216.             if (!atmatch()) {              /* Test if at least "resync" */
  217.                 match = FALSE;             /* consecutive lines match   */
  218.                 break;
  219.                 }
  220.             advance(0); advance(1);       /* Advance over matched lines*/
  221.             }
  222.         while (hold) {
  223.             backup(0); backup(1);         /* Back up over matched lines*/
  224.             --hold;
  225.             }
  226.         } while (!match);                /* Repeat synch until match found */
  227.     difflen [left] = loffset;
  228.     difflen [right] = roffset;
  229.     while (loffset) {
  230.         backup(left); --loffset;         /* Back up over unmatched data */
  231.         }
  232.     while (roffset) {
  233.         backup(right); --roffset;
  234.